package com.powernode.ssm.service;


import com.powernode.ssm.config.FtpConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;

/**
 * FTP 服务类，封装常用的 FTP 操作，例如上传、下载、删除、列出文件等。
 * 使用 Apache Commons Net 的 FTPClient 实现，支持配置被动模式、编码等。
 */
@Slf4j
@Service
public class FtpService {

    private final FtpConfig ftpConfig;
    private FTPClient ftpClient;

    @Autowired
    public FtpService(FtpConfig ftpConfig) {
        this.ftpConfig = ftpConfig;
        this.ftpClient = new FTPClient();
    }

    /**
     * 连接到 FTP 服务器
     *
     * @return 是否连接并登录成功
     */
    public boolean connect() {
        try {
            // 连接 FTP 服务器
            ftpClient.connect(ftpConfig.getHost(), ftpConfig.getPort());
            int replyCode = ftpClient.getReplyCode();

            if (!FTPReply.isPositiveCompletion(replyCode)) {
                log.error("FTP 服务器拒绝连接，回复代码: {}", replyCode);
                disconnect(); // 断开无效连接
                return false;
            }

            // 登录
            boolean loginSuccess = ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword());
            if (!loginSuccess) {
                log.error("FTP 登录失败，用户名或密码错误");
                disconnect();
                return false;
            }

            // 设置文件传输编码（解决中文乱码问题）
            if (ftpConfig.getEncoding() != null) {
                ftpClient.setControlEncoding(ftpConfig.getEncoding());
            }

            // 设置为被动模式（推荐，避免防火墙问题）
            if (ftpConfig.isPassiveMode()) {
                ftpClient.enterLocalPassiveMode();
            }

            // 设置为二进制传输模式（适合图片、压缩包等）
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            log.info("FTP 连接成功：{}:{}", ftpConfig.getHost(), ftpConfig.getPort());
            return true;

        } catch (IOException e) {
            log.error("FTP 连接或登录异常", e);
            disconnect(); // 发生异常也要断开
            return false;
        }
    }

    /**
     * 断开与 FTP 服务器的连接
     */
    public void disconnect() {
        try {
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.logout();  // 退出登录
                ftpClient.disconnect(); // 断开连接
                log.info("FTP 连接已断开");
            }
        } catch (IOException e) {
            log.warn("FTP 断开连接时发生异常", e);
        } finally {
            ftpClient = null;
        }
    }

    /**
     * 上传文件到 FTP 服务器
     *
     * @param remoteFilePath 远程文件路径，如：/upload/test.txt
     * @param inputStream    要上传的文件输入流
     * @return 是否上传成功
     */
    public boolean uploadFile(String remoteFilePath, InputStream inputStream) {
        try {
            if (!isConnected()) {
                if (!connect()) {
                    log.error("未连接到 FTP 服务器，无法上传");
                    return false;
                }
            }

            // 开启被动模式 & 二进制模式（冗余保障，已在connect设置）
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            boolean success = ftpClient.storeFile(remoteFilePath, inputStream);
            if (!success) {
                log.error("文件上传失败，远程路径: {}", remoteFilePath);
            } else {
                log.info("文件上传成功：{}", remoteFilePath);
            }
            return success;
        } catch (IOException e) {
            log.error("文件上传异常：{}", remoteFilePath, e);
            return false;
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.warn("关闭输入流异常", e);
            }
        }
    }

    /**
     * 从 FTP 服务器下载文件
     *
     * @param remoteFilePath 远程文件路径，如：/upload/test.txt
     * @param outputStream   输出流，用于接收下载内容
     * @return 是否下载成功
     */
    public boolean downloadFile(String remoteFilePath, OutputStream outputStream) {
        try {
            if (!isConnected()) {
                if (!connect()) {
                    log.error("未连接到 FTP 服务器，无法下载");
                    return false;
                }
            }

            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            boolean success = ftpClient.retrieveFile(remoteFilePath, outputStream);
            if (!success) {
                log.error("文件下载失败，远程路径: {}", remoteFilePath);
            } else {
                log.info("文件下载成功：{}", remoteFilePath);
            }
            return success;
        } catch (IOException e) {
            log.error("文件下载异常：{}", remoteFilePath, e);
            return false;
        }
    }

    /**
     * 删除 FTP 服务器上的文件
     *
     * @param remoteFilePath 远程文件路径
     * @return 是否删除成功
     */
    public boolean deleteFile(String remoteFilePath) {
        try {
            if (!isConnected()) {
                if (!connect()) {
                    return false;
                }
            }

            boolean success = ftpClient.deleteFile(remoteFilePath);
            if (success) {
                log.info("文件删除成功：{}", remoteFilePath);
            } else {
                log.error("文件删除失败：{}", remoteFilePath);
            }
            return success;
        } catch (IOException e) {
            log.error("删除文件异常：{}", remoteFilePath, e);
            return false;
        }
    }

    /**
     * 列出指定目录下的文件名列表
     *
     * @param remoteDirPath 远程目录路径，如：/upload/
     * @return 文件名字符串数组，如果失败返回空数组
     */
    public String[] listFileNames(String remoteDirPath) {
        try {
            if (!isConnected()) {
                if (!connect()) {
                    return new String[0];
                }
            }

            ftpClient.enterLocalPassiveMode();
            FTPFile[] files = ftpClient.listFiles(remoteDirPath);
            String[] names = new String[files.length];
            for (int i = 0; i < files.length; i++) {
                names[i] = files[i].getName();
            }
            return names;
        } catch (IOException e) {
            log.error("列出文件异常，目录：{}", remoteDirPath, e);
            return new String[0];
        }
    }

    /**
     * 判断当前是否已连接 FTP
     */
    public boolean isConnected() {
        try {
            return ftpClient != null && ftpClient.isConnected();
        } catch (Exception e) {
            return false;
        }
    }
}